package com.monas.client.export;

import static org.apache.poi.hssf.record.PaletteRecord.FIRST_COLOR_INDEX;
import static org.apache.poi.hssf.record.PaletteRecord.STANDARD_PALETTE_SIZE;

import org.apache.poi.hssf.usermodel.HSSFPalette;
import org.apache.poi.hssf.util.HSSFColor;
import org.eclipse.swt.graphics.RGB;

/**
 * Class untuk menentukan warna dalam meng-ekspor excel documents.
 * 
 * @author 'EkoWahyudi'
 * 
 */
public class ExcelColor {

	/**
	 * Maximum index palette.
	 */
	private final static byte MAX = FIRST_COLOR_INDEX + STANDARD_PALETTE_SIZE;

	/**
	 * Tempat warna custom excel.
	 */
	private final HSSFPalette palette;

	/**
	 * Dibuat dengan tempat warna custom excel.
	 * 
	 * @param palette
	 *            warna custom excel
	 */
	public ExcelColor(HSSFPalette palette) {
		this.palette = palette;

		/**
		 * Reset semua warna di palette.
		 */
		for (short index = FIRST_COLOR_INDEX; index < MAX; index++) {
			palette.setColorAtIndex(index, (byte) -1, (byte) -1, (byte) -1);
		}
	}

	/**
	 * Ambil index warna di palette.
	 * 
	 * @param rgb
	 *            warna sempurna.
	 * @return index warna di palette, atau yang dekat jika tidak di temukan
	 *         yang persis sama.
	 */
	public short getIndex(RGB rgb) {
		byte red = (byte) rgb.red;
		byte green = (byte) rgb.green;
		byte blue = (byte) rgb.blue;
		HSSFColor color = findMatch(red, green, blue);
		if (color == null) {
			short blankSlotIndex = getBlankSlotIndex();
			if (blankSlotIndex != -1) {
				palette.setColorAtIndex(blankSlotIndex, red, green, blue);
				System.out.println("Add color " + rgb);
				color = palette.getColor(blankSlotIndex);
			} else {
				color = palette.findSimilarColor(red, green, blue);
			}
		}
		return color.getIndex();
	}

	/**
	 * Apakah masih ada slot selain warna putih.
	 * 
	 * @return true jika ada atau false jika sudah tidak ada lagi.
	 */
	private short getBlankSlotIndex() {
		for (byte index = FIRST_COLOR_INDEX; index < MAX; index++) {
			HSSFColor color = palette.getColor(index);
			short[] rgb = color.getTriplet();
			if (isWhite(rgb)) {
				return index;
			}
		}
		return -1;
	}

	public HSSFColor findMatch(byte red, byte green, byte blue) {
		for (byte index = FIRST_COLOR_INDEX; index < MAX; index++) {
			HSSFColor color = palette.getColor(index);
			short[] rgb = color.getTriplet();
			if (!isWhite(rgb)) {
				if (isMatch(rgb, red, green, blue)) {
					return color;
				}
			}
		}
		return null;
	}

	private boolean isMatch(short[] rgb, byte red, byte green, byte blue) {
		return (byte) rgb[0] == red && (byte) rgb[1] == green
				&& (byte) rgb[2] == blue;
	}

	private boolean isWhite(short[] rgb) {
		return (byte) rgb[0] == (byte) 0xff && (byte) rgb[1] == (byte) 0xff
				&& (byte) rgb[2] == (byte) 0xff;
	}
}
